package com.enation.app.javashop.core.orderbill.service.impl;

import com.dag.eagleshop.core.account.model.dto.account.AccountDTO;
import com.dag.eagleshop.core.account.model.enums.AccountTypeEnum;
import com.dag.eagleshop.core.account.service.AccountManager;
import com.enation.app.javashop.core.client.distribution.DistributionSellerBillClient;
import com.enation.app.javashop.core.client.member.ShopClient;
import com.enation.app.javashop.core.distribution.model.dto.DistributionSellerBillDTO;
import com.enation.app.javashop.core.member.model.dos.Member;
import com.enation.app.javashop.core.member.service.MemberManager;
import com.enation.app.javashop.core.orderbill.model.enums.BillStatusEnum;
import com.enation.app.javashop.core.orderbill.model.vo.BillResult;
import com.enation.app.javashop.core.orderbill.service.BillCountManager;
import com.enation.app.javashop.core.orderbill.service.BillItemManager;
import com.enation.app.javashop.core.orderbill.service.BillManager;
import com.enation.app.javashop.core.orderbill.utils.SettleUtils;
import com.enation.app.javashop.core.shop.model.dos.ShopDO;
import com.enation.app.javashop.core.shop.model.dos.ShopDetailDO;
import com.enation.app.javashop.framework.context.UserContext;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.util.CurrencyUtil;
import com.enation.app.javashop.framework.util.DateUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import org.assertj.core.util.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 结算单统计类
 * @author 孙建
 */
@Service
public class BillCountImpl implements BillCountManager {

    @Autowired
    @Qualifier("tradeDaoSupport")
    private DaoSupport daoSupport;

    @Autowired
    private DistributionSellerBillClient distributionSellerBillClient;
    @Autowired
    private ShopClient shopClient;
    @Autowired
    private BillItemManager billItemManager;
    @Autowired
    private BillManager billManager;
    @Autowired
    private MemberManager memberManager;
    @Autowired
    private AccountManager accountManager;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 计算卖家各种余额
     */
    @Override
    public Map<String, Object> countAccount(Integer sellerId) {
        // 查询虚拟账户金额
        Member member = memberManager.getModel(UserContext.getSeller().getUid());
        String accountMemberId = member.getAccountMemberId();
        AccountDTO accountDTO = accountManager.queryByMemberIdAndAccountType(accountMemberId, AccountTypeEnum.MEMBER_MASTER.getIndex());

        // 计算结算单可提现金额
        BigDecimal withdrawPrice = countPassPrice(sellerId);

        // 计算未对账金额 如果结算单可提现金额或者未对账金额大于0 将余额展示在未对账中
        BigDecimal outPrice = countOutPrice(sellerId);
        if(withdrawPrice.doubleValue() > 0 || outPrice.doubleValue() > 0){
            outPrice = outPrice.add(accountDTO.getBalanceAmount());
        }

        // 计算未出账金额
        BigDecimal countNoOutPrice = BigDecimal.ZERO;
        long countStartTime = billManager.getLastBillEndTime(sellerId);
        if(!SettleUtils.isGoOnline(DateUtil.getDateline())){
            logger.debug("上线前统计未出账金额");
            countNoOutPrice = countNoOutPrice(sellerId, countStartTime, System.currentTimeMillis() / 1000);
        }else{
            logger.debug("上线后统计未出账金额");
            // 查询上线前剩余的结算单内容
            long endTime = SettleUtils.NEW_ACCOUNT_GO_ONLINE_TIME;
            if(endTime > countStartTime){
                logger.debug("统计之前的未出账金额");
                countNoOutPrice = countNoOutPrice(sellerId, countStartTime, endTime);
            }
            // 查询未结算到虚拟账户的金额
            BigDecimal noSettlePrice = billItemManager.countNoSettlePrice(sellerId);
            // 未出账+未结算
            countNoOutPrice = countNoOutPrice.add(noSettlePrice);
        }

        // 封装结果
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("withdrawPrice", withdrawPrice.doubleValue() == 0 ? accountDTO.getBalanceAmount() : withdrawPrice);
        resultMap.put("outPrice", outPrice);
        resultMap.put("noOutPrice", countNoOutPrice);
        resultMap.put("accountId", accountDTO.getId());
        return resultMap;
    }


    /**
     * 统计可提现金额
     */
    @Override
    public BigDecimal countPassPrice(Integer sellerId){
        // 这是以前的结算单逻辑 需要将流程走完
        String sql = "select sum(bill_price) from es_bill where seller_id = ? and status = ?";
        return BigDecimal.valueOf(this.daoSupport.queryForDouble(sql, sellerId, BillStatusEnum.PASS.name()));
    }


    /**
     * 计算未对账金额
     */
    private BigDecimal countOutPrice(Integer sellerId){
        String sql = "select sum(bill_price) from es_bill where seller_id = ? and ( status = ? or status = ?)";
        return BigDecimal.valueOf(this.daoSupport.queryForDouble(sql, sellerId, BillStatusEnum.OUT.name(), BillStatusEnum.RECON.name()));
    }


    /**
     * 计算未出账金额
     */
    private BigDecimal countNoOutPrice(Integer sellerId, Long startTime, Long endTime) {
        // 查询商铺
        ShopDO shop = shopClient.getShopById(sellerId);
        List<ShopDetailDO> shopDetailList = shopClient.getShopDetailByIds(Lists.newArrayList(shop.getShopId()));
        ShopDetailDO shopDetailDO = shopDetailList.get(0);

        //获取分销商品返现支出
        List<DistributionSellerBillDTO> dsbs = distributionSellerBillClient.countSeller(sellerId, startTime, endTime);

        // 结束时间
        String lastTime = String.valueOf(endTime);
        // 统计各卖家的结算结果
        Map<Integer, BillResult> billMap = this.billItemManager.countBillResultMap(String.valueOf(startTime), lastTime);

        //佣金比例
        double shopCommission = shopDetailDO.getShopCommission() == null ? 0.00 : shopDetailDO.getShopCommission();
        Double commissionRate =  shopCommission/ 100;

        BillResult billRes = billMap.get(sellerId);
        //为空说明上个结算周期没有响应没有订单记录
        if (billRes == null) {
            billRes = new BillResult(0.00, 0.00, 0.00, 0.00, sellerId);
        }
        //在线支付的总收入金额
        Double onlinePrice = billRes.getOnlinePrice();
        //在线支付退款的金额
        Double onlineRefundPrice = billRes.getOnlineRefundPrice();
        // 货到付款的总收入金额
        Double codPrice = billRes.getCodPrice();
        // 货到付款的退款金额
        Double codRefundPrice = billRes.getCodRefundPrice();
        //佣金 总收入*佣金比例
        Double commissionPrice = CurrencyUtil.mul(CurrencyUtil.add(onlinePrice, codPrice), commissionRate);
        //退还佣金
        Double refundCommissionPrice = CurrencyUtil.mul(CurrencyUtil.add(onlineRefundPrice, codRefundPrice), commissionRate);

        //分销商品返现
        Double distributionGoodsRebate = 0d;
        //分销商品退单返现返还
        Double distributionReturnRebate = 0d;
        if (StringUtil.isNotEmpty(dsbs)) {
            for (DistributionSellerBillDTO dsb : dsbs) {
                if (dsb.getSellerId().equals(sellerId)) {
                    if (dsb.getCountExpenditure() != null) {
                        distributionGoodsRebate = dsb.getCountExpenditure();
                    }
                    if (dsb.getReturnExpenditure() != null) {
                        distributionReturnRebate = dsb.getReturnExpenditure();
                    }
                }
            }
        }
        //结算金额 = 在线支付金额-在线退款金额-(佣金-退还佣金)
        Double billPrice = CurrencyUtil.sub(CurrencyUtil.sub(onlinePrice, onlineRefundPrice), CurrencyUtil.sub(commissionPrice, refundCommissionPrice));
        //   分销结算 =(分销返现佣金支付-分销返现佣金退换)
        Double distributionBillPrice = CurrencyUtil.sub(distributionGoodsRebate, distributionReturnRebate);

        //最终结算金额=商家结算-分销结算
        billPrice = CurrencyUtil.sub(billPrice, distributionBillPrice);
        return BigDecimal.valueOf(billPrice);
    }

}
